﻿/*
* Copyright 2009-2010 AKABANA.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
using System;
using System.Collections.Generic;


namespace Akabana.Amf.Amf3
{
    internal class Amf3ReferenceTable : IAmfReferenceTable
    {
        private const int NO_REFERENCE = -1;

        private List<string> stringRefList = new List<string>();

        private List<object> objectRefList = new List<object>();

        private List<Traits> traitsRefList = new List<Traits>();

        private Dictionary<string, int> stringRefIndexMap = new Dictionary<string, int>();

        private Dictionary<int, int> objectRefIndexMap = new Dictionary<int, int>();

        private Dictionary<string, int> traitsRefIndexMap = new Dictionary<string, int>();

        public void Clear()
        {
            stringRefList.Clear();
            objectRefList.Clear();
            traitsRefList.Clear();
            stringRefIndexMap.Clear();
            traitsRefIndexMap.Clear();
        }

        public int GetStringIndex(string value)
        {
            int result = NO_REFERENCE;
            if (!stringRefIndexMap.TryGetValue(value, out result))
            {
                result = NO_REFERENCE;
            }
            return result;
        }

        public void SetString(string value)
        {
            stringRefList.Add(value);
            stringRefIndexMap.Add(value, stringRefList.Count - 1);
        }

        public string GetString(int index)
        {
            return String.Copy((string)stringRefList[index]);
        }


        public int GetObjectIndex(object value)
        {
            int result = NO_REFERENCE;
            /*
            var refernceSize = objectRefList.Count;
            for (int i = 0; i < refernceSize; i++)
            {
                if (objectRefList[i] == value)
                {
                    result = i;
                    break;
                }
            }
            */
            if (!objectRefIndexMap.TryGetValue(value.GetHashCode(), out result))
            {
                result = NO_REFERENCE;
            }
            return result;
        }

        public void SetObject(object value)
        {
            objectRefList.Add(value);
            objectRefIndexMap.Add(value.GetHashCode(), objectRefList.Count - 1);
        }

        public object GetObject(int index)
        {
            return objectRefList[index];
        }


        public int GetTraitsIndex(string value)
        {
            int result = NO_REFERENCE;
            if (!traitsRefIndexMap.TryGetValue(value, out result))
            {
                result = NO_REFERENCE;
            }
            return result;
        }

        public void SetTraits(Traits value)
        {
            traitsRefList.Add(value);
            traitsRefIndexMap.Add(value.className, traitsRefList.Count - 1);
        }

        public Traits GetTraits(int index)
        {
            return traitsRefList[index];
        }
    }
}
